/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * NuGat-API named Chameleon developed by Simon De Baets to Verimag.
 *
 */


package chameleon.model.NuGatManager;

import chameleon.gameSolver.NuGat.NuGatInterface;
import chameleon.model.NuGatStructure.fsm.GameSexpFsm;
import chameleon.model.NuGatStructure.utils.Node;
import chameleon.model.NuGatStructure.utils.NodeList;
import chameleon.model.NuGatStructure.prop.PropDbGame;
import chameleon.model.formula.Formula;
import chameleon.model.formula.parser.BooleanParser;
import com.sun.jna.Pointer;
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.xml.sax.SAXException;

/**
 *
 * This class creates a link between some variables and her representation in
 * NuGat.
 *
 * @author simon
 */
public class SymbTableFactory {

    private NuGatInterface nugat_;
    private PropDbGame propDbGame_;

    public SymbTableFactory(PropDbGame propDbGame,NuGatInterface nugat){
        nugat_ = nugat;
        propDbGame_ = propDbGame;
    }

    /**
     * This function etbalish link between a variable and his node representation
     * in NuGat. If parameter mapTable is null, we just return a link between
     * the variable and his node in NuGat.
     *
     * Otherwise we create a link between the user input variable and his representation
     * in NuGat. This correspondance is described in the mapTable.
     * 
     * The structure for the mapTable file is the following
     * graphicalRepresenation smvRepresentation \n
     *
     * @param mapTable
     * @return
     */

    public Hashtable createSymboleTable(File mapTable){
        if (mapTable == null)
            return createSmvMapTable();
        else
            return createMapTable(mapTable);
    }

    /**
     * This function create a link between variables given on input and her
     * NuGat representation.
     *
     * The structure for the mapTable file is the following
     * graphicalRepresenation smvRepresentation \n
     *
     * where graphicalRepresentation is an atomic proposition or a label in
     * the automata.
     *
     * @param mapTable (smvTable)
     * @return
     */

    private Hashtable createMapTable(File mapTable) {
        Hashtable hashTable = null;
        Hashtable smvTable;
        InputStream ips = null;


        //try {
            hashTable = new Hashtable();
            /*ips = new FileInputStream(mapTable);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
            String line;


            while ((line = br.readLine()) !=null){
                String[] atomicProp = line.split(" ");
                hashTable.put(atomicProp[0], atomicProp[1]);
            }*/
            
            
            DOMParser parser = new DOMParser();
            try {
                parser.parse(mapTable.getPath());
            } catch (SAXException ex) {
                Logger.getLogger(NuGatManager.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(NuGatManager.class.getName()).log(Level.SEVERE, null, ex);
            }
            Document document = parser.getDocument();

            Element automata = document.getDocumentElement();
            org.w3c.dom.NodeList state = automata.getElementsByTagName("State");
            org.w3c.dom.NodeList label = automata.getElementsByTagName("Label");
            
            for (int i=0; i < state.getLength(); ++i){
                NamedNodeMap attributes = state.item(i).getAttributes();
                String key = attributes.getNamedItem("sid").getNodeValue();
                String value = label.item(i).getFirstChild().getNodeValue();
                hashTable.put("s"+key,value);
            }

            smvTable = createSmvMapTable();
            hashTable = concateneTable(hashTable,smvTable);

        /*} catch (IOException ex) {
            Logger.getLogger(NuGatManager.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                ips.close();
            } catch (IOException ex) {
                Logger.getLogger(NuGatManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }*/


        return hashTable;
    }

    /** This function put in an Hashtable all the NuGaT variables, and store
     * a the node_ptr corresponding in NuGaT
     *
     */

    private Hashtable createSmvMapTable() {
        Pointer scalar_fsm =
               propDbGame_.getGameScalarSexpFsm();
        
        GameSexpFsm gameSexpFsm = new GameSexpFsm(scalar_fsm, nugat_);

        NodeList varP1_NodeList = gameSexpFsm.getVarsList1();
        NodeList varP2_NodeList = gameSexpFsm.getVarsList2();

        //key : smv representation, value : node_ptr
        Hashtable tmpTable = new Hashtable();

        tmpTable = addPlayerToSmvMapTable(varP1_NodeList, tmpTable);
        tmpTable = addPlayerToSmvMapTable(varP2_NodeList, tmpTable);

        return tmpTable;

    }


    /** this method add all player's variables to the smv map table.
     *  So this table contains a link between all the game's variables and her
     *  node representation in NuGat.
     * @param var_NodeList_ptr
     */
    private Hashtable addPlayerToSmvMapTable(NodeList varList, Hashtable table) {
        Pointer iter;

        for (iter = varList.getFirstIter();
                !varList.ListIterIsEnd(iter);
                iter = varList.ListIterGetNext(iter)){
            Node node = varList.getElemAt(iter);

            /**
             * key : string representation
             * value : pointer to NuGat node
             */

            table.put(node.sprintNode(), node);
        }
        return table;
    }

    /** This function take in paramter a hashTable which the structure is :
     * key : graph representation, value : smv representation
     *
     * and an smvTable which the structure is :
     *  key : smv representation, value : node_ptre
     *
     * and return an hashatble that have structure
     *
     * key : graph representation, value : node_ptr
     *
     * @param hashTable
     * @param smvTable
     * @return
     */

    private Hashtable concateneTable(Hashtable hashTable, Hashtable smvTable) {
        Hashtable result = new Hashtable();
        Set symbol = hashTable.keySet();
        Iterator iter = symbol.iterator();
        while(iter.hasNext()){
            try {
                Object current = iter.next();
                String smvSymbol = (String) hashTable.get(current.toString());
                BooleanParser parser = new BooleanParser(smvSymbol);
                Formula smvRepresentation = parser.createFormula();
                Object value = smvRepresentation.encFormula(nugat_, smvTable);
                result.put(current.toString(),value);
            } catch (IOException ex) {
                Logger.getLogger(NuGatManager.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return result;
    }


}
